package study_thread;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * 阶段锁
 * 所有人到达同一阶段才可以
 *
 * @author: 李德才
 * @description:
 * @create: 2020-12-12 20:15
 **/
public class Test_Phaser {


    /**
     * Phaser（移相器，一种电子元件）是JDK7中引入的新的并发工具辅助类，
     * oralce官网文档描述Phaser是一个可重复使用的同步栅栏，功能上与 CountDownLatch 和 CyclicBarrier类似但支持的场景更加灵活，
     * Phaser的灵活性主要体现在在构造函数时不需要强制指定目前有多少参与协作的线程，可以在运行时动态改变
     *      Phaser() //默认的构造方法，初始化注册的线程数量为0
     *      Phaser(int parties)//一个指定线程数量的构造方法
     */

    /**
     * 阶段锁/阶段器
     * 所有线程到达同一阶段才可以继续执行
     * Phaser类提供的同步线程机制是在每个步骤的末端， 所以全部的线程都完成第一步后，才能开始执行第二步。
     */

    /**
     * register()//添加一个新的注册者
     * bulkRegister(int parties)//添加指定数量的多个注册者
     * arrive()// 到达栅栏点直接执行，无须等待其他的线程
     * arriveAndAwaitAdvance()//到达栅栏点，必须等待其他所有注册者到达
     * arriveAndDeregister()//到达栅栏点，注销自己无须等待其他的注册者到达
     * onAdvance(int phase, int registeredParties)//多个线程达到注册点之后，会调用该方法。
     * isTerminated()：判断Phaser是否终止。
     */

    static Random r = new Random();

    static class MarriagePhaser extends Phaser {
        @Override
        protected boolean onAdvance(int phase, int registeredParties) {
            switch (phase) {
                case 0:
                    System.out.println("所有人到齐了！" + registeredParties);
                    System.out.println();
                    return false;
                case 1:
                    System.out.println("所有人吃完了！" + registeredParties);
                    System.out.println();
                    return false;
                case 2:
                    System.out.println("所有人离开了！" + registeredParties);
                    System.out.println();
                    return false;
                case 3:
                    System.out.println("婚礼结束！" + registeredParties);
                    return true;
                default:
                    return true;
            }
        }
    }

    static MarriagePhaser phaser = new MarriagePhaser();

    static void milliSleep(int milli) {
        try {
            TimeUnit.MILLISECONDS.sleep(milli);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        phaser.bulkRegister(7);
        for (int i = 0; i < 5; i++) {
            new Thread(new Person("p" + i)).start();
        }
        new Thread(new Person("新郎")).start();
        new Thread(new Person("新娘")).start();
    }



    static class Person implements Runnable {
        String name;


        @Override
        public void run() {
            arrive();
            eat();
            leave();
            hug();
        }


        public Person(String name) {
            this.name = name;
        }

        public void arrive() {
            milliSleep(r.nextInt(1000));
            System.out.printf("%s 到达现场！\n", name);
            phaser.arriveAndAwaitAdvance();
        }

        public void eat() {
            milliSleep(r.nextInt(1000));
            System.out.printf("%s 吃完!\n", name);
            phaser.arriveAndAwaitAdvance();
        }

        public void leave() {
            milliSleep(r.nextInt(1000));
            System.out.printf("%s 离开！\n", name);
            phaser.arriveAndAwaitAdvance();
        }

        private void hug() {
            if (name.equals("新郎") || name.equals("新娘")) {
                milliSleep(r.nextInt(1000));
                System.out.printf("%s 洞房！\n", name);
                phaser.arriveAndAwaitAdvance();
            } else {
                phaser.arriveAndDeregister();
            }
        }


    }
}
